Skip to main content

Arrays

An array in Rust is a fixed-size collection of elements of the same type, stored contiguously in memory.

Rust arrays are simple, fast, and safe, but not growable.

let arr = [1, 2, 3, 4, 5];
  • All elements must be the same type
  • Length is known at compile time
  • Stored on the stack (by default)

Type of an Array

let arr: [i32; 5] = [1, 2, 3, 4, 5];

Syntax:

[element_type; number_of_elements]

Key Characteristics of Arrays

FeatureArrays
SizeFixed
MemoryContiguous
Grow/Shrink❌ No
IndexingO(1)
SafetyBounds-checked
MutabilityOptional

Creating Arrays

  • Standard Initialization: let numbers = [10, 20, 30, 40];
  • Initialize with Same Value: let zeros = [0; 5]; Creates: [0, 0, 0, 0, 0]
  • Mutable Array: let mut scores = [50, 60, 70];scores[1] = 85;

Accessing Array Elements

Using Index

let arr = [1, 2, 3];

println!("{}", arr[0]); // 1

Out-of-Bounds Access (Runtime Panic)

let arr = [1, 2, 3];
let x = arr[10]; // ❌ panic

Rust performs runtime bounds checking to ensure safety.

Safe Access Using .get()

let arr = [1, 2, 3];

match arr.get(10) {
Some(value) => println!("{}", value),
None => println!("Index out of bounds"),
}

Iterating Over Arrays

Using for Loop (Recommended)

let arr = [10, 20, 30];

for value in arr {
println!("{}", value);
}

📌 This works because arrays implement Copy for small types.

Using Index-Based Loop

let arr = [10, 20, 30];

for i in 0..arr.len() {
println!("Index {} = {}", i, arr[i]);
}

Using Iterator Methods

let arr = [1, 2, 3, 4];

for value in arr.iter() {
println!("{}", value);
}

Array Slices (&[T])

A slice is a reference to part (or all) of an array.

let arr = [1, 2, 3, 4, 5];
let slice = &arr[1..4];

slice type: &[i32]

Slice Properties

FeatureSlice
Ownership❌ No
SizeDynamic
MutabilityDepends
MemoryBorrowed

Mutable Slice

let mut arr = [1, 2, 3, 4];
let slice = &mut arr[1..3];

slice[0] = 20;

Array becomes: [1, 20, 3, 4]

Arrays vs Vectors (Very Important)

FeatureArrayVector (Vec<T>)
SizeFixedDynamic
MemoryStackHeap
Resize
Use caseKnown-size dataFlexible collections

Use arrays when:

  • Size is fixed
  • Performance is critical
  • Data is small

Use vectors when:

  • Size may change
  • Input comes from users/files

Passing Arrays to Functions

Passing by Reference (Best Practice)

fn print_array(arr: &[i32]) {
for x in arr {
println!("{}", x);
}
}

Usage:

let numbers = [1, 2, 3];
print_array(&numbers);

&[i32] works for: Arrays, Slices, Vectors

Passing Fixed-Size Array

fn sum(arr: [i32; 3]) -> i32 {
arr.iter().sum()
}

Less flexible (size must match exactly).

Multidimensional Arrays

2D Array Example

let matrix = [
[1, 2, 3],
[4, 5, 6],
];

Access Elements: println!("{}", matrix[1][2]); // 6

Iterating 2D Arrays

for row in matrix {
for val in row {
print!("{} ", val);
}
println!();
}

Memory Safety Highlights

  • Fixed size prevents unexpected reallocations
  • Bounds checking prevents buffer overflows
  • Ownership rules prevent data races

Rust arrays are low-level but safe.